package com.gzdh.tang.dishrecognition.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gzdh.tang.comm.handler.IPayRuleHandler;
import com.gzdh.tang.comm.util.ObjectUtil;
import com.gzdh.tang.comm.vo.Result;
import com.gzdh.tang.dishrecognition.dto.DiningTableListDto;
import com.gzdh.tang.dishrecognition.dto.JiaoBanDto;
import com.gzdh.tang.dishrecognition.dto.LcReportDto;
import com.gzdh.tang.dishrecognition.dto.ReserveListDto;
import com.gzdh.tang.dishrecognition.mapper.DrPublicMapper;
import com.gzdh.tang.dishrecognition.model.*;
import com.gzdh.tang.mobile.entity.Bmcm;
import com.gzdh.tang.mobile.service.BmcmService;
import com.gzdh.tang.modu.entity.*;
import com.gzdh.tang.modu.service.*;
import com.gzdh.tang.modu.util.DateUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@RequestMapping("dr/orders")
public class DrOrderController {
    @Autowired
    MacMainpSbruanService macMainpSbruanService;

    @Autowired
    MacMainpSbruanPayruleService macMainpSbruanPayruleService;

    @Autowired
    MacMainpSbruanDinnerService macMainpSbruanDinnerService;

    @Autowired
    MacMainpSbruanKlService macMainpSbruanKlService;

    @Autowired
    FkService fkService;

    @Autowired
    BmcmService bmcmService;

    @Autowired
    ReserveService reserveService;

    @Autowired
    DrPublicMapper drPublicMapper;

    @PostMapping("unOnLine")
    public Result<Object> unOnLine(@RequestBody JSONObject jsonObject) throws Exception {
        Result<Object> result = new Result<>();
        OrdersReq ordersReq = jsonObject.getObject("orders", OrdersReq.class);
        try {
            List<OrdersDetailsReq> ordersDetailsReqList = jsonObject.getJSONArray("details").toJavaList(OrdersDetailsReq.class);
            PayModelReq payModelReq = new PayModelReq();
            payModelReq.setAuth(ordersReq.getCardsn());
            payModelReq.setCzrq(ordersReq.getCreateTime());
            payModelReq.setPayWay(1);
            payModelReq.setSc(ordersReq.getType());
            payModelReq.setDeviceId(ordersReq.getDeviceId());
            payModelReq.setUserId(ordersReq.getUserId());
            payModelReq.setOrders(ordersReq.getOrders());
            payModelReq.setIgnoreException(true);
            List<WeekMenuBakModelReq> weekMenuBakModelReqList = new ArrayList<>();
            for (OrdersDetailsReq goo : ordersDetailsReqList) {
                WeekMenuBakModelReq weekMenuBakModelReq = new WeekMenuBakModelReq();
                weekMenuBakModelReq.setZl(goo.getZl());
                weekMenuBakModelReq.setDinner(goo.getDinner());
                weekMenuBakModelReq.setName(goo.getName());
                weekMenuBakModelReq.setBm(goo.getBm());
                weekMenuBakModelReq.setNumber(goo.getNumber());
                weekMenuBakModelReq.setPrice(goo.getPrice());
                weekMenuBakModelReq.setAddr(goo.getAddr());
                weekMenuBakModelReqList.add(weekMenuBakModelReq);
            }
            payModelReq.setProductCartModelList(weekMenuBakModelReqList);
            IPayRuleHandler ruleHandler = null;
            String deviceId = jsonObject.getString("deviceId");
            if (StringUtils.isNotEmpty(deviceId)) {
                MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>().lambda()
                        .eq(MacMainpSbruan::getMac, deviceId));
                if (macMainpSbruan == null) {
                    return Result.error("设备未找到或者设备有误，请核对操作");
                }
                MacMainpSbruanPayrule macMainpSbruanPayrule = macMainpSbruanPayruleService.getById(macMainpSbruan.getPayRule());
                ruleHandler = (IPayRuleHandler) Class
                        .forName(macMainpSbruanPayrule.getClassName())
                        .newInstance();
            } else {
                ruleHandler = (IPayRuleHandler) Class
                        .forName("com.gzdh.tang.dishrecognition.rule.DrTedcPaytRule")
                        .newInstance();
            }
            String jsonStr = JSONObject.toJSONString(payModelReq);
            JSONObject resJson = ruleHandler.toCardPay(JSONObject.parseObject(jsonStr));
            jsonObject.putAll(resJson);
        } catch (RuntimeException e) {
            e.printStackTrace();
            result.setCode(500);
            result.setMessage(e.getMessage());
        }
        return result;
    }

    @GetMapping("getLcReport")
    public Result<Object> getLcReport(@RequestParam("deviceId") String deviceId, @RequestParam("auth") String auth) {
        Result<Object> result = new Result<>();
        MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>().lambda()
                .eq(MacMainpSbruan::getMac, deviceId));
        String dinner = getDinner(macMainpSbruan);
        Bmcm bmcm = bmcmService.getOne(new QueryWrapper<Bmcm>().lambda().eq(Bmcm::getBm, dinner));
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("dinner", dinner);
        resMap.put("bmcm", bmcm);
        Fk fk;
        if (auth.length() <= 8) {
            fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardsn, auth));
        } else {
            byte[] bytes = Base64.getDecoder().decode(auth);
            String json = new String(bytes);
            String cardNo = json.split(",")[0].split("=")[1];
            fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardno, cardNo));
        }
        if (fk == null) {
            return Result.error("非法卡");
        }
        resMap.put("fk", fk);
        String dates = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date());
        List<LcReportDto> lcReportDtoList = drPublicMapper.getLcReport(fk.getCardno(), dinner, dates);
        resMap.put("lcData", lcReportDtoList);
        result.setResult(resMap);
        return result;
    }

    @GetMapping("getTakeFoodList")
    public Result<Object> getTakeFoodList(@RequestParam("deviceId") String deviceId, @RequestParam("auth") String auth) {
        MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>().lambda()
                .eq(MacMainpSbruan::getMac, deviceId));
        String dinner = getDinner(macMainpSbruan);
        Bmcm bmcm = bmcmService.getOne(new QueryWrapper<Bmcm>().lambda().eq(Bmcm::getBm, dinner));
        Map<String, Object> resMap = new HashMap<>();
        resMap.put("dinner", dinner);
        resMap.put("dinnerName", bmcm.getName());
        Fk fk;
        if (auth.length() <= 8) {
            fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardsn, auth));
        } else {
            try {
                byte[] bytes = Base64.getDecoder().decode(auth);
                String json = new String(bytes);
                String cardNo = json.split(",")[0].split("=")[1];
                String timestamp = json.split(",")[2].split("=")[1];
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
                Date date = dateFormat.parse(timestamp);
                if(new Date().getTime() - date.getTime() > (1000*60*30)) {
                    return Result.error("此领餐码已过有效期");
                }
                fk = fkService.getOne(new QueryWrapper<Fk>().lambda().eq(Fk::getCardno, cardNo));
            } catch (Exception e) {
                return Result.error("领餐码格式有误");
            }
        }
        if (fk == null) {
            return Result.error("非法卡");
        }
        QueryWrapper<MacMainpSbruanKl> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("device_id", macMainpSbruan.getId());
        queryWrapper.eq("kl", fk.getKl());
        if(macMainpSbruanKlService.count(queryWrapper) == 0) {
            return Result.error("此卡类不存在");
        }
        resMap.put("fk", fk);
        String dates = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(new Date());
        List<LcReportDto> list = drPublicMapper.getTakeFoodList(fk.getCardno(), dinner, dates);
        resMap.put("dataList", list);
        return new Result<>("查询成功", 0, resMap);
    }

    @GetMapping("receiveFood")
    public Result<Object> receiveFood(@RequestParam("pkIdList") List<Long> pkIdList) {
        StringBuilder sqlString = new StringBuilder();
        if(pkIdList.size() > 0) {
            for (Long pkId : pkIdList) {
                sqlString.append(pkId).append(",");
            }
            sqlString.deleteCharAt(sqlString.length() - 1);
        }
        String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date());
        Integer row = drPublicMapper.receiveFood(1, date, sqlString.toString());
        if(row > 0) {
            return new Result<>("操作成功", 0, null);
        }
        return Result.error("操作异常");
    }


    private String getDinner(MacMainpSbruan macMainpSbruan) throws RuntimeException {
        try {
            String hourMin = new SimpleDateFormat("HH:mm").format(new Date());
            List<MacMainpSbruanDinner> macMainpSbruanDinnerList = macMainpSbruanDinnerService
                    .list(new QueryWrapper<MacMainpSbruanDinner>().lambda().eq(MacMainpSbruanDinner::getDeviceId,
                            macMainpSbruan.getId()));
            for (MacMainpSbruanDinner goo : macMainpSbruanDinnerList) {
                if (DateUtil.hourMinuteBetween(hourMin, goo.getStartTime(), goo.getEndTime())) {
                    return goo.getDinner();
                }
            }
            throw new Exception("找不到该餐次");
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage());
        }
    }


    @GetMapping("getOrderList")
    public Result<Object> getOrderList(@Param("startTime") String startTime,
                                       @Param("endTime") String endTime,
                                       @Param("deviceId") String deviceId) {
        Result<Object> result = new Result<>();
        List<ReserveListDto> reserveListDtoList = reserveService.getOrderList(startTime, endTime, deviceId);
        result.setResult(reserveListDtoList);
        return result;
    }

    @GetMapping("getDiningTableList")
    public Result<Object> getDiningTableList(@Param("type") Integer type,
                                             @Param("startTime") String startTime,
                                             @Param("endTime") String endTime,
                                             @Param("bqh") String bqh,
                                             @Param("ksh") String ksh) {
        Result<Object> result = new Result<>();
        List<DiningTableListDto> list = reserveService.getDiningTableList(type, startTime, endTime, bqh, ksh);
        result.setResult(list);
        return result;
    }

    @GetMapping("getOrderDetails")
    public Result<Object> getOrderDetails(@RequestParam("orders") String orders) {
        Result<Object> result = new Result<>();

        List<Reserve> reserveList = reserveService.list(new QueryWrapper<Reserve>().lambda()
                .eq(Reserve::getZfserialnumber, orders));
        result.setResult(reserveList);
        return result;
    }

    @GetMapping("getDiningTableDetails")
    public Result<Object> getDiningTableDetails(@RequestParam("ksh") String ksh,
                                                @RequestParam("dinner") String dinner,
                                                @RequestParam("dcTime") String dcTime,
                                                @RequestParam("useTimes") String useTimes) {
        Result<Object> result = new Result<>();
        List<Reserve> reserveList = reserveService.getDiningTableDetails(ksh, dinner, dcTime, useTimes);
        List<Map<String,Object>> list = new LinkedList<>();
        for (Reserve reserve : reserveList) {
            Map<String,Object> map = new HashMap<>();
            map.put("hName", ObjectUtil.getStr(reserve.getHname()));
            map.put("number", ObjectUtil.getStr(reserve.getSl()));
            map.put("price", ObjectUtil.getStr(reserve.getJe()));
            list.add(map);
        }
        result.setResult(list);
        return result;
    }

    @GetMapping("cleanDiningTable")
    public Result<Object> cleanDiningTable(@RequestParam("ksh") String ksh,
                                           @RequestParam("dinner") String dinner,
                                           @RequestParam("dcTime") String dcTime) {
        Map<String, Object> params = new HashMap<>();
        params.put("ksh", ksh);
        params.put("dinner", dinner);
        params.put("dcTime", dcTime);
        String maxUseTimes = reserveService.getMaxUseTimes(params);
        params.put("times", ObjectUtil.getInt(maxUseTimes) + 1);
        Integer row = reserveService.updateUseTimes(params);
        Result<Object> result = new Result<>();
        if (row <= 0) {
            result.error500("操作失败");
        }
        return result;
    }

    @GetMapping("getJiaoBan")
    public Result<Object> getJiaoBan(@RequestParam("startTime") String startTime,
                                     @RequestParam("endTime") String endTime,
                                     @RequestParam("posNumList") List<String> posNumList,
                                     @Param("deviceId") String deviceId) {
        Result<Object> result = new Result<>();
        MacMainpSbruan macMainpSbruan = macMainpSbruanService.getOne(new QueryWrapper<MacMainpSbruan>().lambda()
                .eq(MacMainpSbruan::getMac, deviceId));
        if (macMainpSbruan.getUsePostType() == 0) {
            posNumList.clear();
            posNumList.add(macMainpSbruan.getPos());
        }
        JiaoBanRes jiaoBanRes = new JiaoBanRes();
        jiaoBanRes.setStartTime(startTime);
        jiaoBanRes.setEndTime(endTime);
        StringBuilder sqlString = new StringBuilder(" and posnum <> '31'");
        if(posNumList != null && posNumList.size() > 0) {
            sqlString.append(" and posNum in (");
            for (String posNum : posNumList) {
                sqlString.append("'").append(posNum).append("',");
            }
            sqlString.deleteCharAt(sqlString.length() - 1);
            sqlString.append(")");
        }
        Map<String, Object> params = new HashMap<>();
        params.put("startTime", startTime);
        params.put("endTime", endTime);
        params.put("sqlString", sqlString);
        params.put("symbol", ">");
        List<JiaoBanDto> payHandoverList = drPublicMapper.handoverWork(params);
        params.put("symbol", "<");
        List<JiaoBanDto> refundHandoverList = drPublicMapper.handoverWork(params);
        for (JiaoBanDto goo : refundHandoverList) {
            //退款
            jiaoBanRes.setCounts(jiaoBanRes.getCounts() - goo.getCounts());
            jiaoBanRes.setAmount(new BigDecimal(jiaoBanRes.getAmount()).add(new BigDecimal(goo.getPrice()))
                    .setScale(2, RoundingMode.HALF_UP).toPlainString());
            if("0".equals(goo.getSc())) {
                //自购
                jiaoBanRes.setZgAmount2(goo.getPrice());
                jiaoBanRes.setZgCounts2(goo.getCounts());
                jiaoBanRes.setZZgCounts(jiaoBanRes.getZZgCounts() - goo.getCounts());
                jiaoBanRes.setZZgAmount(new BigDecimal(jiaoBanRes.getZZgAmount()).add(new BigDecimal(goo.getPrice()))
                        .setScale(2, RoundingMode.HALF_UP).toPlainString());
            } else if ("1".equals(goo.getSc())) {
                //补贴
                jiaoBanRes.setBtAmount2(goo.getPrice());
                jiaoBanRes.setBtCounts2(goo.getCounts());
                jiaoBanRes.setZBtCounts(jiaoBanRes.getZBtCounts() - goo.getCounts());
                jiaoBanRes.setZBtAmount(new BigDecimal(jiaoBanRes.getZBtAmount()).add(new BigDecimal(goo.getPrice()))
                        .setScale(2, RoundingMode.HALF_UP).toPlainString());
            } else if ("2".equals(goo.getSc())) {
                //现金
                jiaoBanRes.setCashAmount2(goo.getPrice());
                jiaoBanRes.setCashCounts2(goo.getCounts());
                jiaoBanRes.setZCashCounts(jiaoBanRes.getZCashCounts() - goo.getCounts());
                jiaoBanRes.setZCashAmount(new BigDecimal(jiaoBanRes.getZCashAmount()).add(new BigDecimal(goo.getPrice()))
                        .setScale(2, RoundingMode.HALF_UP).toPlainString());
            } else if ("3".equals(goo.getSc())) {
                //微信
                jiaoBanRes.setWxAmount2(goo.getPrice());
                jiaoBanRes.setWxCounts2(goo.getCounts());
                jiaoBanRes.setZWxCounts(jiaoBanRes.getZWxCounts() - goo.getCounts());
                jiaoBanRes.setZWxAmount(new BigDecimal(jiaoBanRes.getZWxAmount()).add(new BigDecimal(goo.getPrice()))
                        .setScale(2, RoundingMode.HALF_UP).toPlainString());
            } else {
                //聚合支付
                jiaoBanRes.setLsAmount2(goo.getPrice());
                jiaoBanRes.setLsCounts2(goo.getCounts());
                jiaoBanRes.setZLsCounts(jiaoBanRes.getZLsCounts() - goo.getCounts());
                jiaoBanRes.setZLsAmount(new BigDecimal(jiaoBanRes.getZLsAmount()).add(new BigDecimal(goo.getPrice()))
                        .setScale(2, RoundingMode.HALF_UP).toPlainString());
            }
        }

        for (JiaoBanDto goo : payHandoverList) {
            //退款
            jiaoBanRes.setCounts(jiaoBanRes.getCounts() + goo.getCounts());
            jiaoBanRes.setAmount(new BigDecimal(jiaoBanRes.getAmount()).add(new BigDecimal(goo.getPrice()))
                    .setScale(2, RoundingMode.HALF_UP).toPlainString());

            jiaoBanRes.setZCounts(jiaoBanRes.getZCounts() + goo.getCounts());
            jiaoBanRes.setZAmount(new BigDecimal(jiaoBanRes.getZAmount()).add(new BigDecimal(goo.getPrice()))
                    .setScale(2, RoundingMode.HALF_UP).toPlainString());
            if("0".equals(goo.getSc())) {
                //自购
                jiaoBanRes.setZgAmount1(goo.getPrice());
                jiaoBanRes.setZgCounts1(goo.getCounts());
                jiaoBanRes.setZZgCounts(jiaoBanRes.getZZgCounts() + goo.getCounts());
                jiaoBanRes.setZZgAmount(new BigDecimal(jiaoBanRes.getZZgAmount()).add(new BigDecimal(goo.getPrice()))
                        .setScale(2, RoundingMode.HALF_UP).toPlainString());
            } else if ("1".equals(goo.getSc())) {
                //补贴
                jiaoBanRes.setBtAmount1(goo.getPrice());
                jiaoBanRes.setBtCounts1(goo.getCounts());
                jiaoBanRes.setZBtCounts(jiaoBanRes.getZBtCounts() + goo.getCounts());
                jiaoBanRes.setZBtAmount(new BigDecimal(jiaoBanRes.getZBtAmount()).add(new BigDecimal(goo.getPrice()))
                        .setScale(2, RoundingMode.HALF_UP).toPlainString());
            } else if ("2".equals(goo.getSc())) {
                //现金
                jiaoBanRes.setCashAmount1(goo.getPrice());
                jiaoBanRes.setCashCounts1(goo.getCounts());
                jiaoBanRes.setZCashCounts(jiaoBanRes.getZCashCounts() + goo.getCounts());
                jiaoBanRes.setZCashAmount(new BigDecimal(jiaoBanRes.getZCashAmount()).add(new BigDecimal(goo.getPrice()))
                        .setScale(2, RoundingMode.HALF_UP).toPlainString());
            } else if ("3".equals(goo.getSc())){
                jiaoBanRes.setWxAmount1(goo.getPrice());
                jiaoBanRes.setWxCounts1(goo.getCounts());
                jiaoBanRes.setZWxCounts(jiaoBanRes.getZWxCounts() + goo.getCounts());
                jiaoBanRes.setZWxAmount(new BigDecimal(jiaoBanRes.getZWxAmount()).add(new BigDecimal(goo.getPrice()))
                        .setScale(2, RoundingMode.HALF_UP).toPlainString());
            } else {
                jiaoBanRes.setLsAmount1(goo.getPrice());
                jiaoBanRes.setLsCounts1(goo.getCounts());
                jiaoBanRes.setZLsCounts(jiaoBanRes.getZLsCounts() + goo.getCounts());
                jiaoBanRes.setZLsAmount(new BigDecimal(jiaoBanRes.getZLsAmount()).add(new BigDecimal(goo.getPrice()))
                        .setScale(2, RoundingMode.HALF_UP).toPlainString());
            }
        }
        result.setResult(jiaoBanRes);
        return result;
    }
}
